package com.rtc.call.core

import android.content.Context
import android.content.Intent
import android.media.AudioDeviceInfo
import android.nfc.NfcAdapter
import android.os.Build
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import com.rtc.call.core.data.ConfigResponse
import io.agora.rtc2.RtcEngine
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

/**
 * CallCore - Main entry point for the RTC call functionality.
 * Handles the app initialization, MQTT, NFC, and RTC channel management as per the flow diagram.
 */
class CallCore private constructor(private val context: Context) {
    
    private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
    private var rtcEngine: RtcEngine? = null
    private var nfcAdapter: NfcAdapter? = null
    private val configManager: ConfigManager by lazy { ConfigManager(context) }
    private val nfcManager: NfcManager by lazy { NfcManager(context, configManager) }
    private val callManager: CallManager by lazy { CallManager(context, rtcEngine, configManager) }
    private val mqttClient: MqttClient by lazy { MqttClient(context, coroutineScope,configManager) }

    private val TAG = "CallCore"
    private var configData :ConfigResponse? = null
    private var agoraAppId: String? =null
    private var agoraChannel: String? = null
    private var agoraToken: String? = null
    companion object {
        @Volatile
        private var INSTANCE: CallCore? = null
        
        fun getInstance(context: Context): CallCore {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: CallCore(context.applicationContext).also { INSTANCE = it }
            }
        }
    }

    fun  initialize() {
        initNfcAdapter()
        //        mqttClient.connect(
//            onMqttConnected = {
//                // Load initial configuration
//                configManager.loadTurnOnConfig(coroutineScope, appId)
//
//                // Observe configuration changes
//                observeConfigChanges()
//            },
//            onMqttDisconnected = {
//                // Handle MQTT disconnection
//            }
//        )
        observeConfigChange()
    }
    fun  loadTurnOnConfig() {
        configManager.loadTurnOnConfig(coroutineScope)
    }

    fun loadNfcOnConfig() {
        configManager.lastNfcId = configManager.nfcId
        configManager.nfcId = "1D:51:A0:C1:0B:10:80"
        configManager.loadNfcOnConfig(coroutineScope,"","1D:51:A0:C1:0B:10:80",agoraAppId,agoraChannel,agoraToken)
    }

    fun loadNfcOffConfig() {
        configManager.lastNfcId = configManager.nfcId
        configManager.nfcId = ""
        configManager.loadNfcOffConfig(coroutineScope,"1D:51:A0:C1:0B:10:80","",agoraAppId,agoraChannel,agoraToken)
    }
    /**
     * Initialize the CallCore module
     * This is the first step as per the flow diagram - "APP开启" (App Start)
     */
    fun initialize(appId: String, lifecycleOwner: LifecycleOwner) {
        // Initialize RTC Engine
        initRtcEngine(appId)
        
        // Initialize NFC adapter
        initNfcAdapter()
        
        // Connect to MQTT server
//        mqttClient.connect(
//            onMqttConnected = {
//                // Load initial configuration
//                configManager.loadTurnOnConfig(coroutineScope, appId)
//
//                // Observe configuration changes
//                observeConfigChanges()
//            },
//            onMqttDisconnected = {
//                // Handle MQTT disconnection
//            }
//        )
        
        // Apply lifecycle observation
        observeLifecycle(lifecycleOwner)
    }

    private fun observeConfigChange() {
        coroutineScope.launch {
            configManager.configState.collectLatest { result ->
                result?.getOrNull()?.let{
                    configData = it
                    if (it.welcomeMp3.isNotEmpty()) {
                       playNetWorkSound(it.welcomeMp3) {
                           startCall(it)
                       }
                    } else {
                        startCall(it)
                    }

                }
            }
        }

    }

    private fun startCall(it: ConfigResponse) {
        if (!it.agoraAppId.isNullOrEmpty() && !it.agoraChannel.isNullOrEmpty()) {
            if ( agoraAppId != it.agoraAppId) {
                agoraAppId = it.agoraAppId
                initRtcEngine(it.agoraAppId)

            }
            if (agoraChannel != it.agoraChannel && agoraToken != it.agoraToken) {
                agoraChannel = it.agoraChannel.orEmpty()
                agoraToken = it.agoraToken.orEmpty()
                enterRtcChannel(agoraChannel!!,0,agoraToken)
//                            startDefaultCall()
//                            startNfcDetection()
            }
        } else {
            Log.d(TAG,"config error agoraAppId = ${it.agoraAppId}   ,agoraChannel = ${it.agoraChannel}")
        }
    }
    /**
     * Observe configuration changes
     */
    private fun observeConfigChanges() {
        coroutineScope.launch {
            configManager.turnOnConfigState.collectLatest { result ->
                result?.getOrNull()?.let {
                    // Config loaded, update UI or settings
                    callManager.updateFromConfig(ConfigManager.CONFIG_TYPE_TURNON)
                }
            }
        }
        
        coroutineScope.launch {
            configManager.nfcOnConfigState.collectLatest { result ->
                result?.getOrNull()?.let {
                    // Config loaded, update UI or settings
                    callManager.updateFromConfig(ConfigManager.CONFIG_TYPE_NFCON)
                }
            }
        }
        
        coroutineScope.launch {
            configManager.nfcOffConfigState.collectLatest { result ->
                result?.getOrNull()?.let {
                    // Config loaded, update UI or settings
                    callManager.updateFromConfig(ConfigManager.CONFIG_TYPE_NFCOFF)
                }
            }
        }
    }
    

    /**
     * Start the RTC channel based on the flow diagram
     */
    fun enterRtcChannel(channelName: String, uid: Int, token: String? = null) {
        callManager.joinChannel(channelName, uid, token)
    }
    fun saveDeviceId(deviceId: String) {
        configManager.saveDeviceId(deviceId)
    }

    fun getDeviceId(): String {
        return configManager.getDeviceId(context)
    }
    /**
     * Start NFC detection
     */
    fun startNfcDetection() {
        nfcManager.startNfcDetection { nfcResult ->
            when (nfcResult) {
                is NfcResult.NfcOn -> {
                    // NFC贴上 - Handle NFC sticker detected
//                    configManager.loadNfcOnConfig(coroutineScope, configManager.getAppId(ConfigManager.CONFIG_TYPE_TURNON))
//                    // Play special sound and turn on lights
//                    callManager.playGreetingSound()
//                    callManager.turnOnLights()
                    Log.d(TAG,"NfcResult.NfcOn")
                }
                is NfcResult.NfcOff -> {
                    Log.d(TAG,"NfcResult.NfcOff")
                    // NFC拿开 - Handle NFC sticker removed
//                    configManager.loadNfcOffConfig(coroutineScope, configManager.getAppId(ConfigManager.CONFIG_TYPE_TURNON))
//                    // Turn off lights
//                    callManager.turnOffLights()
//                    callManager.playEndingSound()
                }
            }
        }
    }

    fun  playNetWorkSound(url:String,onCompletion: () -> Unit = {}) {
        callManager.playNetWorkSound(url,onCompletion)
    }
    /**
     * Handle default and colorful calls
     */
    fun startDefaultCall() {
        callManager.startDefaultCall()
    }
    
    fun startColorfulCall() {
        callManager.startColorfulCall()
    }


    /**
     * Sets the audio input device to use
     *
     * @param deviceId The ID of the audio input device to use
     * @return true if successful, false otherwise
     */
    fun setAudioInputDevice(deviceId: Int): Boolean {
        try {
            if (rtcEngine == null) {
                Log.e(TAG, "RTC Engine is not initialized")
                return false
            }
            
            // Use Android's audio device type for matching
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // For Android M and above, try to match the device type
                when (deviceId) {
                    AudioDeviceInfo.TYPE_BUILTIN_MIC -> {
                        // 使用内置麦克风
                        rtcEngine?.setDefaultAudioRoutetoSpeakerphone(false)
                        return true
                    }
                    AudioDeviceInfo.TYPE_WIRED_HEADSET -> {
                        // 使用有线耳机/麦克风
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    AudioDeviceInfo.TYPE_USB_DEVICE, AudioDeviceInfo.TYPE_USB_HEADSET -> {
                        // 使用USB设备或USB耳机/麦克风
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    AudioDeviceInfo.TYPE_BLUETOOTH_SCO -> {
                        // 使用蓝牙设备
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    else -> {
                        // 默认使用扬声器
                        rtcEngine?.setDefaultAudioRoutetoSpeakerphone(true)
                        return true
                    }
                }
            } else {
                // 对于Android 6.0以下版本，只能简单地设置音频路由
                rtcEngine?.setDefaultAudioRoutetoSpeakerphone(false)
                return true
            }
            
            return false
        } catch (e: Exception) {
            Log.e(TAG, "Error setting audio input device: ${e.message}")
            return false
        }
    }
    
    /**
     * Sets the audio output device to use
     *
     * @param deviceId The ID of the audio output device to use
     * @return true if successful, false otherwise
     */
    fun setAudioOutputDevice(deviceId: Int): Boolean {
        try {
            if (rtcEngine == null) {
                Log.e(TAG, "RTC Engine is not initialized")
                return false
            }
            
            // Use Android's audio device type for matching
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                // For Android M and above, try to match the device type
                when (deviceId) {
                    AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> {
                        // 使用扬声器
                        rtcEngine?.setEnableSpeakerphone(true)
                        return true
                    }
                    AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
                    AudioDeviceInfo.TYPE_WIRED_HEADSET -> {
                        // 使用有线耳机或有线耳机/麦克风
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    AudioDeviceInfo.TYPE_USB_DEVICE,
                    AudioDeviceInfo.TYPE_USB_HEADSET -> {
                        // 使用USB设备或USB耳机/麦克风
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
                    AudioDeviceInfo.TYPE_BLUETOOTH_A2DP -> {
                        // 使用蓝牙设备
                        rtcEngine?.setEnableSpeakerphone(false)
                        return true
                    }
                    else -> {
                        // 默认使用扬声器
                        rtcEngine?.setEnableSpeakerphone(true)
                        return true
                    }
                }
            } else {
                // 对于Android 6.0以下版本，根据设备ID简单设置是否使用扬声器
                if (deviceId == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
                    rtcEngine?.setEnableSpeakerphone(true)
                } else {
                    rtcEngine?.setEnableSpeakerphone(false)
                }
                return true
            }
            
            return false
        } catch (e: Exception) {
            Log.e(TAG, "Error setting audio output device: ${e.message}")
            return false
        }
    }

    /**
     * Sets the default audio route to speakerphone
     * @param speakerOn Whether to use speakerphone (true) or earpiece (false) as the default audio route
     */
    fun setDefaultAudioRouteToSpeakerphone(speakerOn: Boolean) {
        rtcEngine?.setDefaultAudioRoutetoSpeakerphone(speakerOn)
//        RtcEngineManager.setDefaultAudioRouteToSpeakerphone(rtcEngine, speakerOn)
    }
    
    /**
     * Get the NFC manager for advanced operations
     * Renamed to avoid conflict with property accessor
     */
    fun getPublicNfcManager(): NfcManager? {
        return nfcManager
    }
    
    /**
     * Handle NFC intent from Activity
     */
    fun handleNfcIntent(intent: Intent) {
        nfcManager.processNfcIntent(intent)
    }
    
    /**
     * Simulate NFC tag removal (for testing purposes)
     */
    fun simulateNfcRemove() {
        nfcManager.simulateNfcTagRemoved()
    }
    
    private fun initRtcEngine(appId: String) {
        rtcEngine = RtcEngineManager.createRtcEngine(context, appId)
        callManager.updateRtcEngine(rtcEngine!!)
    }
    
    private fun initNfcAdapter() {
        nfcAdapter = NfcAdapter.getDefaultAdapter(context)
        nfcManager.setNfcAdapter(nfcAdapter)
    }
    
    private fun observeLifecycle(lifecycleOwner: LifecycleOwner) {
        // Observe lifecycle to properly clean up resources
    }
    
    /**
     * Clean up resources when the module is no longer needed
     */
    fun destroy() {
        mqttClient.disconnect()
        nfcManager.stopNfcDetection()
        callManager.leaveChannel()
        rtcEngine?.leaveChannel()
        RtcEngine.destroy()
        rtcEngine = null
        INSTANCE = null
    }
} 